package com.zhong.thesimpleconnection.action;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.hyphenate.EMCallBack;
import com.hyphenate.chat.EMClient;
import com.zhong.bmob.inter.IFileUpLoadUserDown;
import com.zhong.bmob.inter.ILoginUserDown;
import com.zhong.bmob.inter.IRegisterUserDown;
import com.zhong.bmob.model.User;
import com.zhong.bmob.server.FileUpLoad;
import com.zhong.bmob.server.Login;
import com.zhong.bmob.server.Register;
import com.zhong.thesimpleconnection.R;
import com.zhong.thesimpleconnection.model.Constant;
import com.zhong.thesimpleconnection.model.FileSavePath;
import com.zhong.thesimpleconnection.service.ServiceToMonitorFile;
import com.zhong.thesimpleconnection.util.CryptUtil;
import com.zhong.thesimpleconnection.util.EMClientHelper;
import com.zhong.thesimpleconnection.util.NativeHelper;
import com.zhong.thesimpleconnection.util.PermissionUtils;
import com.zhong.thesimpleconnection.util.getToBytes;
import com.zhong.thesimpleconnection.view.MyDialogWarn;

import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;

public class LoginActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener, View.OnClickListener, TextWatcher, IFileUpLoadUserDown, IRegisterUserDown, ILoginUserDown {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    private LinearLayout mLayoutLogin;
    private int height;
    private int viewHeight;
    private EditText userName;
    private EditText userPassword;
    private Button login;
    private Button register;
    private ImageView seeOrNot;
    private int state;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 521:
                    stopWait();
                    startWait(4);
                    break;
            }
        }
    };
    private MyDialogWarn mWarn;
    private User mUser;
    private StringBuilder mBuilder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        setListener();
    }

    private void setListener() {
        seeOrNot.setOnClickListener(this);
        login.setOnClickListener(this);
        register.setOnClickListener(this);
        userPassword.addTextChangedListener(this);
    }

    /**
     * 开始登录框的动画
     */
    private void setAnimator() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            ObjectAnimator animator = ObjectAnimator.ofFloat(
                    mLayoutLogin,
                    "Y",
                    height,
                    height / 2 - viewHeight / 2).setDuration(3000);
            animator.start();
        }
    }

    private void init() {
        state = 1;
        seeOrNot = (ImageView) findViewById(R.id.Login_To_User_Password_See);
        userName = (EditText) findViewById(R.id.Login_To_User_Name);
        userPassword = (EditText) findViewById(R.id.Login_To_User_Password);
        login = (Button) findViewById(R.id.Login_To_Login);
        register = (Button) findViewById(R.id.Login_To_Register);
        mLayoutLogin = (LinearLayout) findViewById(R.id.LoginToApp);
        WindowManager windowManager = (WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        height = windowManager.getDefaultDisplay().getHeight();
        ViewTreeObserver observer = mLayoutLogin.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(this);
        Intent intent = new Intent(this, ServiceToMonitorFile.class);
        startService(intent);
    }

    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mLayoutLogin.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            viewHeight = mLayoutLogin.getHeight();
            setAnimator();
        }
    }

    @Override
    public void onClick(View view) {
        int id = view.getId();
        switch (id) {
            case R.id.Login_To_User_Password_See:
                if (state == 1){
                    //将密码切换为可见的
                    userPassword.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
                    seeOrNot.setImageResource(R.mipmap.cansee);
                    state = 0;
                } else {
                    //将密码切换为不可见的
                    userPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
                    seeOrNot.setImageResource(R.mipmap.cannotsee);
                    state = 1;
                }
                userPassword.postInvalidate();
                break;
            case R.id.Login_To_Login:
                String userNameLogin = userName.getText().toString().trim();
                String userPasswordLogin = userPassword.getText().toString().trim();
                if (!userNameLogin.equals("") && !userPasswordLogin.equals("")) {
                    startWait(1);
                    doThingLogin(userNameLogin, userPasswordLogin);
                } else {
                    startWait(2);
                }
                break;
            case R.id.Login_To_Register:
                String userNameString = userName.getText().toString().trim();
                String userPasswordString = userPassword.getText().toString().trim();
                if (!userNameString.equals("") && !userPasswordString.equals("")) {
                    startWait(1);
                    doThing(userNameString, userPasswordString);
                } else {
                    startWait(2);
                }
                break;
            default:
                break;
        }
    }

    private void doThingLogin(String userNameString, String userPasswordString) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                User user = new User();
                user.setUsername(userNameString);
                mBuilder = getUserPasswordCrypt(userPasswordString);
                user.setPassword(mBuilder.toString());
                Login.userLogin(user, LoginActivity.this);
            }
        }).start();
    }

    private void doThing(String userNameString, String userPasswordString) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                File saveKeyPath = FileSavePath.getSaveKeyPath(1);
                if (saveKeyPath != null) {
                    Message message = new Message();
                    message.what = Constant.KeyFilesAreExist;
                    mHandler.sendMessage(message);
                } else {
                    //生成自己的钥匙对，公钥上传到服务器，私钥存在自己的手机本地文件夹中
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        PermissionUtils.requestPermission(LoginActivity.this, PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE, mPermissionGrant);
                    } else {
                        CryptUtil.saveSecret();
                    }
                    File path = FileSavePath.getSaveKeyPath(FileSavePath.TYPE_GETSAVE_PUBLICKEY_PATH);
                    if (path != null) {
                        mUser = new User();
                        mUser.setUsername(userNameString);
                        mBuilder = getUserPasswordCrypt(userPasswordString);
                        mUser.setPassword(mBuilder.toString());
                        FileUpLoad.getFilePath(path, LoginActivity.this);
                    } else {

                    }
                }
            }
        }).start();
    }

    /**
     * 用于加密用户输入的密码
     * @param userPasswordString 原始密码数据
     * @return 加密后的密码数据
     */
    @NonNull
    private StringBuilder getUserPasswordCrypt(String userPasswordString) {
        byte[] aByte = getToBytes.getByte(userPasswordString);
        byte[] secret = NativeHelper.getCryptSecret(aByte);
        byte[] bytes = getToBytes.backFromBinary(secret);
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            builder.append(Constant.listData.charAt(b));
        }
        int inc;
        if (userPasswordString.length() % 3 != 0) {
            int i = userPasswordString.length() / 3 * 4 + 4;
            inc = i - builder.length();
        } else {
            inc = 0;
        }
        for (int i = 0; i < inc; i++) {
            builder.append("=");
        }
        return builder;
    }

    /**
     * 从资源文件中获取指定id所对应的值
     * @param id 资源文件中的id
     * @return 返回指定id所对应的值
     */
    private String getStringFromResource(int id){
        String ret;
        ret = this.getResources().getString(id);
        return ret;
    }

    /**
     * 弹出的Dialog样式
     * @param type type = 1 表示弹出等待Dialog；type = 2、3和4 表示弹出警告Dialog
     */
    public void startWait(int type) {
        String title = null;
        String content = null;
        if (type == 1) {
            title = getStringFromResource(R.string.Dialog_Warn_Wait_Title);
        } else if (type == 2) {
            title = getStringFromResource(R.string.Dialog_Warn_Warn_Title);
            content = getStringFromResource(R.string.Dialog_Warn_Warn_Content);
        } else if (type == 3) {
            title = getStringFromResource(R.string.Dialog_Warn_Warn_Title);
            content = getStringFromResource(R.string.UserPassword_Error);
            type = 2;
        } else if (type == 4) {
            title = getStringFromResource(R.string.Dialog_Warn_Warn_Title);
            content = getStringFromResource(R.string.UserRegister_OnlyCanRegisterOnce_InTheOneEquipment);
            type = 2;
        }
        int finalType = type;
        mWarn = new MyDialogWarn.Builder(this, R.style.MyDialog).
                setTitle(title)
                .setState(type)
                .setContent(content)
                .setCancelable(false)
                .setPositiveButton(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (finalType == 1) {

                        } else {
                            mWarn.dismiss();
                        }
                    }
                })
                .setNegativeButton(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (finalType == 1) {
                            mWarn.dismiss();
                        } else {
                            mWarn.dismiss();
                        }
                    }
                })
                .create();
        mWarn.show();
    }

    /**
     * 取消dialog
     */
    private void stopWait(){
        mWarn.dismiss();
    }

    private PermissionUtils.PermissionGrant mPermissionGrant = new PermissionUtils.PermissionGrant() {
        /**
         * 授权成功后的回调
         * @param requestCode 对应的权限
         */
        @Override
        public void onPermissionGranted(int requestCode) {
            switch (requestCode) {
                case PermissionUtils.CODE_RECORD_AUDIO:

                    break;
                case PermissionUtils.CODE_GET_ACCOUNTS:

                    break;
                case PermissionUtils.CODE_READ_PHONE_STATE:

                    break;
                case PermissionUtils.CODE_CALL_PHONE:

                    break;
                case PermissionUtils.CODE_CAMERA:

                    break;
                case PermissionUtils.CODE_ACCESS_FINE_LOCATION:

                    break;
                case PermissionUtils.CODE_ACCESS_COARSE_LOCATION:

                    break;
                case PermissionUtils.CODE_READ_EXTERNAL_STORAGE:

                    break;
                case PermissionUtils.CODE_WRITE_EXTERNAL_STORAGE:
                    CryptUtil.saveSecret();
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        PermissionUtils.requestPermissionsResult(LoginActivity.this, requestCode, permissions, grantResults, mPermissionGrant);
    }
    
    @Override
    public void beforeTextChanged(CharSequence s, int start,
                                  int count, int after) {

    }

    /**
     * 用于用户输入的密码进行正则匹配
     * @param s 输入的密码
     * @param start 没用到
     * @param before 没用到
     * @param count 没用到
     */
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        String trim = s.toString().trim();
        if (!"".equals(trim)){
            Pattern compile = Pattern.compile("^[a-zA-Z][a-zA-Z0-9]{0,10}");
            Matcher matcher = compile.matcher(s);
            if (!matcher.matches()) {
                startWait(3);
                userPassword.setText("");
            }
        }
    }

    @Override
    public void afterTextChanged(Editable editable) {

    }

    @Override
    public void upLoadSuccess(String fileUrl) {
        mUser.setPublicKeyFile(fileUrl);
        Register.userRegister(mUser, LoginActivity.this);
    }

    @Override
    public void upLoadFail(BmobException exception) {

    }

    @Override
    public void registerSuccess(User user) {
        stopWait();
        Toast.makeText(this, getStringFromResource(R.string.UserRegister_SuccessMessage), Toast.LENGTH_SHORT).show();
        EMClientHelper.getInstance().EMClientRegister(LoginActivity.this, user.getUsername(), mBuilder.toString());
        mBuilder = null;
    }

    @Override
    public void registerFail(BmobException exception) {
        stopWait();
        int code = exception.getErrorCode();
        if (code == 202) {
            Toast.makeText(this, getStringFromResource(R.string.UserRegister_FailMessage_UserNameExist), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void loginSuccess(User user) {
        String pass = mBuilder.toString();
        EMClient.getInstance().login(user.getUsername(), pass, new EMCallBack() {//回调
            @Override
            public void onSuccess() {
                EMClient.getInstance().groupManager().loadAllGroups();
                EMClient.getInstance().chatManager().loadAllConversations();
                Log.d("main", "登录聊天服务器成功！");
                SharedPreferences preferences = getSharedPreferences("User", MODE_PRIVATE);
                SharedPreferences.Editor edit = preferences.edit();
                edit.putString("UserName", user.getUsername());
                edit.putString("State", "已登录");
                edit.apply();
                mBuilder = null;
                stopWait();
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                intent.putExtra("UserMessageAll", user);
                startActivity(intent);
            }

            @Override
            public void onProgress(int progress, String status) {

            }

            @Override
            public void onError(int code, String message) {
                Log.d("main", "登录聊天服务器失败！");
            }
        });
//        EMClientHelper.getInstance().EMClientLogin(LoginActivity.this, user.getUsername(), pass);
    }

    @Override
    public void loginFail(BmobException e) {
        stopWait();
        int code = e.getErrorCode();
    }
}
